package AlexDB.Server;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import AlexDB.MDB.Persistence;
import AlexDB.Resolver.Resolve;
import AlexDB.Resolver.ResolveFactory;

public class ServerApp {
    public static String StartInfos()
    {
        return "AlexDB server start.";
    }

    public static void main(String[] args) throws IOException {

        Runtime.getRuntime().addShutdownHook(new Thread() {

            public void run() {
                System.out.println("program exit . save data...");
                Persistence.clearDbMapProfile();
            }
        
        }); 

        try {
            Persistence.readFromListProfile();

            System.out.println(StartInfos());

            // 使用线程池处理并发用户情况
            ExecutorService executorService = Executors.newFixedThreadPool(20000);

            ServerSocket server = new ServerSocket(2021);
            while (true) {
                final Socket serverSocket = server.accept();
                var address = serverSocket.getInetAddress().getHostAddress().toString();
                System.out.printf("host %s connect. \r\n",address);

                executorService.execute(() -> {
                    ObjectInputStream objinputStream=null;
                    ObjectOutputStream objOutputStream = null;
                    try {
                        boolean isRun = true;
                        while(isRun){
                            objinputStream = new ObjectInputStream(serverSocket.getInputStream());
                            
                            var resolve = ResolveFactory.initialized().CreateResolve();
                            var clientCommand = objinputStream.readUTF();
                            if(clientCommand.equals("exit"))
                            {
                                isRun = false;
                                break;
                            }
                            Object[] commandArgs = resolve.resolveArgs(clientCommand);
                            System.out.printf("[host %s]: "+ clientCommand + "\r\n",address);
                            var result = resolve.resolveCommand(commandArgs).commandExecute(commandArgs);
                            
                            objOutputStream = new ObjectOutputStream(serverSocket.getOutputStream());
                            objOutputStream.writeObject(Resolve.deresolveResultToString(result));
                        }
                        serverSocket.close();
                        System.out.printf("host %s connect is close . save data... \r\n",address);
                        Persistence.writeDbMapProfile();
                    } 
                    catch (IOException e) {
                        try {
                            objOutputStream.writeObject(e.getMessage());
                        } catch (IOException e1) {
                            e1.printStackTrace();
                        }
                    } 
                    catch (Exception e) {
                        try {
                            objOutputStream.writeObject(e.getMessage());
                        } catch (IOException e1) {
                            e1.printStackTrace();
                        }
                    }
                });
            }
        } catch (IOException ex) {
            ex.printStackTrace();
            Persistence.writeDbMapProfile();
        }
    }

    

}
